#include "APP_Buffer.h"

//假溢出:环形缓冲区数据超过了缓冲区边界回到了开始位置 但是环形缓冲区并未写满
//环形缓冲区 写操作:关键点区分一般写入和假溢出写入,一般写入不会超过缓冲边界 但是假溢出写入会超过缓冲边界
//读操作:关键点也是区分的当前缓冲区状态是一般状态还是假溢出状态
//注意: 写入的当前位置是 偏移量+当前数据长度往后一格   读取的当前位置就是偏移量本身的位置,例如偏移量为0
//当前读取位置就位置数组下标0的位置


//初始化环形缓冲区 指定环形缓冲区的大小
Buffer* APP_Buffer_Init(int size)
{
    //初始化  为环形缓冲区的结构体 分配空间
    Buffer* buff = (Buffer*) malloc(sizeof(Buffer));
    if(buff == NULL)
    {
        log_info("缓冲区结构体 初始化失败\n");
        return NULL;
    }
    //为结构体中的环形缓冲区 分配
    buff->ptr = (char*) malloc(sizeof(char) * size);
    if(buff->ptr == NULL)
    {
        log_info("缓冲区指针 初始化失败\n");
        free(buff);
        return NULL;
    }
    //初始化 其余变量
    buff->total_size = size;
    buff->len = 0;
    buff->offset = 0;
    pthread_mutex_init(&buff->lock,NULL);
    //返回环形缓冲区的结构体指针
    return buff;
}

//写数据
void APP_Buffer_Write(Buffer* buff,char* data,int Write_len)
{
    //上锁
    pthread_mutex_lock(&buff->lock);
    //当前位置 使用数组下标那种绝对位置  
    int index = (buff->offset + buff->len - 1) % buff->total_size;
    // 剩余长度
    int Remain_len = buff->total_size - buff->len;
    if(Write_len > Remain_len)
    {
        log_info("写入字节长度大于当前缓冲区长度\n");
        return;
    }
    //假溢出: 环形缓冲区 到达数组边界 返回到数组开头
    // 根据 待写入的数据长度是否会让环形缓冲区出现假溢出 分为两种情况判断
    if((index + Write_len) <= (buff->total_size - 1))//小于等于最大边界
    {
        //继续接着上次的位置 写入 也就是当前位置index + 1
        memcpy(buff->ptr + index + 1,data,Write_len);
    }
    else
    {
        int temp_len = (buff->total_size -1 - index);//当前位置距离边界的长度
        memcpy((buff->ptr + index + 1),data,temp_len);//到达缓冲区边界
        memcpy(buff->ptr,(data + temp_len),(Write_len - temp_len));//假溢出 回到缓冲区起点
    }
    //更新参数
    buff->len += Write_len;

    // //打印写入数据情况
    // log_info("==================================\n");
    // log_info("写入数据为: %.*s ,长度为: %d\n",Write_len,data,Write_len);
    // //打印当前缓冲区的情况
    // // log_info("当前缓冲区数据: %.*s ,偏移量为: %d ,长度为: %d\n",buff->len,(buff->ptr + buff->offset),buff->offset,buff->len);
    // printf("                                     当前缓冲区数据: ");
    // for(int i = 0;i <= (buff->len - 1);i++)
    // {
    //     int index = (buff->offset + i) % buff->total_size;
    //     printf("%c",*(buff->ptr + index));
    // }
    // printf(" ,偏移量为: %d ,长度为: %d\n",buff->offset,buff->len);

    //开锁
    pthread_mutex_unlock(&buff->lock);
}

//读数据  成功:返回读取的字节长度  失败: -1
int APP_Buffer_Read(Buffer* buff, char* data,int Read_len)
{
    //上锁
    pthread_mutex_lock(&buff->lock);
    if (buff->len == 0)
    {
        log_info("当前数据为空无法读取\n");
        return -1;
    }
    
    //比较实际缓冲长度 得出可以读取的字节长度
    Read_len = Read_len < buff->len?Read_len:buff->len;
    //根据当前缓冲区是否出现假溢出 分两种情况讨论
    if((buff->offset + Read_len - 1) <= (buff->total_size - 1))
    {
        memcpy(data,(buff->ptr + buff->offset),Read_len);
    }
    else
    {
        int temp_len = (buff->total_size - buff->offset);//当前头指针偏移量到边界的距离
        memcpy(data,(buff->ptr + buff->offset),temp_len);
        memcpy(data + temp_len,buff->ptr,Read_len - temp_len);
    }
    //更新参数
    buff->len -= Read_len; //数据长度
    buff->offset = (buff->offset + Read_len) % buff->total_size;//偏移量:指向着当前将要读取数据的第一个

    // //打印读取出的数据情况
    // log_info("==================================\n");
    // // log_info("当前缓冲区数据: %.*s ,偏移量为: %d ,长度为: %d\n",buff->len,(buff->ptr + buff->offset),buff->offset,buff->len);
    // printf("                                     当前缓冲区数据: ");
    // for(int i = 0;i <= (buff->len - 1);i++)
    // {
    //     int index = (buff->offset + i) % buff->total_size;
    //     printf("%c",*(buff->ptr + index));
    // }
    // printf(" ,偏移量为: %d ,长度为: %d\n",buff->offset,buff->len);
    // log_info("读取数据为: %.*s ,长度为: %d\n",Read_len,data,Read_len);
    
    //开锁
    pthread_mutex_unlock(&buff->lock);
    return Read_len;
}

//释放环形缓冲区
void APP_Buffer_Free(Buffer* buff)
{
    //先释放 缓冲区
    free(buff->ptr);
    //再释放 缓冲区结构体
    free(buff);
    return;
}
